package com.dognessnetwork.operation.dognecklace.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.repository.JpaRepository;

public abstract class BeanUtil {

	private static String[] getNullProperties(Object src) {
		BeanWrapper srcBean = new BeanWrapperImpl(src);
		PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
		Set<String> emptyName = new HashSet<String>();
		for (PropertyDescriptor p : pds) {
			Object srcValue = srcBean.getPropertyValue(p.getName());
			if (srcValue == null)
				emptyName.add(p.getName());
		}
		String[] result = new String[emptyName.size()];
		return emptyName.toArray(result);
	}

	public static void copyProperties(Object src, Object target) {
		BeanUtils.copyProperties(src, target, getNullProperties(src));
	}

	public static <T, E> T convertTo(E source, Class<T> target) {
		if (source == null) {
			return null;
		}
		try {
			T t = target.newInstance();
			copyProperties(source, t);
			return t;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

	public static <T, E> List<T> convertTo(List<E> source, Class<T> target) {
		if (source == null || source.isEmpty()) {
			return Collections.emptyList();
		}
		return source.stream().map((e) -> convertTo(e, target)).collect(Collectors.toList());
	}

	public static <T> T setNullValue(T source)
			throws IllegalArgumentException, IllegalAccessException, SecurityException {
		Field[] fields = source.getClass().getDeclaredFields();
		for (Field field : fields) {
			if (field.getGenericType().toString().equals("class java.lang.String")) {
				field.setAccessible(true);
				Object obj = field.get(source);
				if (obj != null && obj.equals("")) {
					field.set(source, null);
				} else if (obj != null) {
					String str = obj.toString();
					field.set(source, str.trim());
				}
			}
		}
		return source;
	}

	
	public static PageRequest getPageRequest(Integer page, Integer size) {
		return getPageRequest(page, size, null);
	}
	
	public static PageRequest getPageRequest(Integer page, Integer size, Direction direction, String ... properties) {
		page = (page == null || page < 1) ? 1 : page;
		size = (size == null || size < 1) ? 10 : size;
		return direction == null ? PageRequest.of((page - 1), size) : PageRequest.of((page - 1), size, direction, properties);
	}
	
	public static <T, R extends JpaRepository<T, Long>> Page<T> getPageContent(Integer page, Integer size, T obj,
			R repository) {
		return getPageContent(page, size, obj, repository, null);
	}
	
	public static <T, R extends JpaRepository<T, Long>> Page<T> getPageContent(Integer page, Integer size, T obj,
			R repository, Direction direction, String ... properties) {
		try {
			obj = setNullValue(obj);
		} catch (IllegalArgumentException | IllegalAccessException | SecurityException e) {
			e.printStackTrace();
		}
		
		ExampleMatcher matcher = ExampleMatcher.matching();
		Example<T> example = Example.of(obj, matcher);
		Page<T> content = repository.findAll(example, getPageRequest(page, size, direction, properties));
		return content;
	}
}
